home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / OpenGL / stonehenge / Stone.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  19.4 KB  |  816 lines

  1. /*
  2.  * (c) Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * ALL RIGHTS RESERVED
  4.  * Permission to use, copy, modify, and distribute this software for
  5.  * any purpose and without fee is hereby granted, provided that the above
  6.  * copyright notice appear in all copies and that both the copyright notice
  7.  * and this permission notice appear in supporting documentation, and that
  8.  * the name of Silicon Graphics, Inc. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.
  11.  *
  12.  * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13.  * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15.  * FITNESS FOR A PARTICULAR PURPOSE.  IN NO EVENT SHALL SILICON
  16.  * GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17.  * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18.  * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19.  * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20.  * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC.  HAS BEEN
  21.  * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22.  * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23.  * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24.  *
  25.  * US Government Users Restricted Rights
  26.  * Use, duplication, or disclosure by the Government is subject to
  27.  * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28.  * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29.  * clause at DFARS 252.227-7013 and/or in similar or successor
  30.  * clauses in the FAR or the DOD or NASA FAR Supplement.
  31.  * Unpublished-- rights reserved under the copyright laws of the
  32.  * United States.  Contractor/manufacturer is Silicon Graphics,
  33.  * Inc., 2011 N.  Shoreline Blvd., Mountain View, CA 94039-7311.
  34.  *
  35.  * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36.  */
  37. #include <GL/glu.h>
  38. #include <GL/glx.h>
  39.  
  40. #include <math.h>
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43.  
  44. #include "Stone.h"
  45.  
  46. const GLfloat root2 = 1.4142136;
  47. const GLfloat root3 = sqrt(3.);
  48. const GLfloat rt_half = .70710678;
  49.  
  50. inline float radians(float a) {return M_PI * a / 180.0; }
  51.  
  52. inline float sign(float a) {return (a > 0. ? 1 : (a < 0. ? -1 : 0)); }
  53.  
  54. Stone::Stone() 
  55. {
  56.   translation.set(0, 0, 0);
  57.   rotation = 0;
  58.   dimensions.set(1, 1, 1);
  59.  
  60.   erosion = 0;
  61.  
  62.   points_valid = transforms_valid = 0;
  63. }
  64.  
  65. Stone::~Stone() 
  66. {
  67. }
  68.  
  69. Stone Stone::operator=(Stone a)
  70. {
  71.   int i;
  72.  
  73.   translation = a.translation;
  74.   rotation = a.rotation;
  75.   dimensions = a.dimensions;
  76.  
  77.   erosion = a.erosion;
  78.  
  79.   if (a.points_valid && a.transforms_valid) {
  80.     for (i = 0; i < 24; i++) points[i] = a.points[i];
  81.     points_valid = transforms_valid = 1;
  82.   } else points_valid = transforms_valid = 0;
  83.  
  84.   return *this;
  85. }
  86.  
  87. void Stone::set_dimensions(GLfloat x, GLfloat y, GLfloat z)
  88. {
  89.   dimensions.set(x, y, z);
  90.   points_valid = 0;
  91. }
  92.  
  93. void Stone::set_dimensions(Point p)
  94. {
  95.   dimensions = p;
  96.   points_valid = 0;
  97. }
  98.  
  99. void Stone::erode(float p)
  100. {
  101.   erosion += p;
  102.   points_valid = 0;
  103. }
  104.  
  105. void Stone::translate(GLfloat x, GLfloat y, GLfloat z)
  106. {
  107.   translation.pt[0] += x;
  108.   translation.pt[1] += y;
  109.   translation.pt[2] += z;
  110.   points_valid = 0;
  111. }
  112.  
  113. void Stone::translate(Point p)
  114. {
  115.   translation += p;
  116.   points_valid = 0;
  117. }
  118.  
  119. void Stone::rotate_self_aboutz(GLfloat angle)
  120. {
  121.   rotation += angle;
  122.   points_valid = 0;
  123. }
  124.  
  125. void Stone::draw()
  126. {
  127.   compute_points();
  128.  
  129.   glPushMatrix();
  130.   glRotatef(rotation, 0, 0, 1);
  131.   glTranslatef(translation.pt[0], translation.pt[1], translation.pt[2]);
  132.   glScalef(dimensions.pt[0], dimensions.pt[1], dimensions.pt[2]);
  133.  
  134.   draw_faces();
  135.   draw_edges();
  136.   draw_corners();
  137.  
  138.   glPopMatrix();
  139. }
  140.  
  141. void Stone::compute_points()
  142. {
  143.   GLfloat e = 1.0 - erosion;
  144.  
  145.   if (points_valid) return;
  146.  
  147.   points[0].set(1, e, e);
  148.   points[1].set(e, 1, e);
  149.   points[2].set(e, e, 1);
  150.  
  151.   points[3].set(-e, e, 1);
  152.   points[4].set(-e, 1, e);
  153.   points[5].set(-1, e, e);
  154.  
  155.   points[6].set(e, -e, 1);
  156.   points[7].set(e, -1, e);
  157.   points[8].set(1, -e, e);
  158.  
  159.   points[9 ].set(e, e, -1);
  160.   points[10].set(e, 1, -e);
  161.   points[11].set(1, e, -e);
  162.  
  163.   points[12].set(-1, -e, e);
  164.   points[13].set(-e, -1, e);
  165.   points[14].set(-e, -e, 1);
  166.  
  167.   points[15].set(1, -e, -e);
  168.   points[16].set(e, -1, -e);
  169.   points[17].set(e, -e, -1);
  170.  
  171.   points[18].set(-1, e, -e);
  172.   points[19].set(-e, 1, -e);
  173.   points[20].set(-e, e, -1);
  174.   
  175.   points[21].set(-e, -e, -1);
  176.   points[22].set(-e, -1, -e);
  177.   points[23].set(-1, -e, -e);
  178.  
  179.   points_valid = 1;
  180.   transforms_valid = 0;
  181. }
  182.  
  183. inline Point Stone::trans_rot_point(Point p, float c, float s)
  184. {
  185.   Point val;
  186.   val = p + translation;
  187.   val = val.rotate_aboutz(c, s);
  188.   return val;
  189. }
  190.  
  191. inline Point Stone::transform_point(Point p, float c, float s)
  192. {
  193.   Point val;
  194.   val = p.scale(dimensions);
  195.   val += translation;
  196.   val = val.rotate_aboutz(c, s);
  197.   return val;
  198. }
  199.  
  200. void Stone::transform_points()
  201. {
  202.   float c, s;
  203.   int i;
  204.  
  205.   if (points_valid && transforms_valid) return;
  206.   points_valid = 0;
  207.   compute_points();
  208.  
  209.   c = cos(radians(rotation));
  210.   s = sin(radians(rotation));
  211.  
  212.   for (i = 0; i < 24; i++) points[i] = transform_point(points[i], c, s);
  213.  
  214.   points_valid = 0;
  215.   transforms_valid = 1;
  216. }    
  217.  
  218. void Stone::draw_faces(int flat)
  219. {
  220.   draw_faces(points, flat);
  221. }
  222.  
  223. void Stone::draw_faces(Point *p, int flat)
  224. {
  225.   glBegin(GL_QUADS);
  226.  
  227.   glNormal3f(1, 0, 0);
  228.   if (flat) glTexCoord2fv(p[15].pt);
  229.   else glTexCoord2f(0, 0);
  230.   glVertex3fv(p[15].pt);
  231.   if (flat) glTexCoord2fv(p[11].pt);
  232.   else glTexCoord2f(1, 0);
  233.   glVertex3fv(p[11].pt);
  234.   if (flat) glTexCoord2fv(p[0].pt);
  235.   else glTexCoord2f(1, 1);
  236.   glVertex3fv(p[0].pt);
  237.   if (flat) glTexCoord2fv(p[8].pt);
  238.   else glTexCoord2f(0, 1);
  239.   glVertex3fv(p[8].pt);
  240.  
  241.   glNormal3f(-1, 0, 0);
  242.   if (flat) glTexCoord2fv(p[12].pt);
  243.   else glTexCoord2f(0, 0);
  244.   glVertex3fv(p[12].pt);
  245.   if (flat) glTexCoord2fv(p[5].pt);
  246.   else glTexCoord2f(1, 0);
  247.   glVertex3fv(p[5].pt);
  248.   if (flat) glTexCoord2fv(p[18].pt);
  249.   else glTexCoord2f(1, 1);
  250.   glVertex3fv(p[18].pt);
  251.   if (flat) glTexCoord2fv(p[23].pt);
  252.   else glTexCoord2f(0, 1);
  253.   glVertex3fv(p[23].pt);
  254.  
  255.   glNormal3f(0, 1, 0);
  256.   if (flat) glTexCoord2fv(p[4].pt);
  257.   else glTexCoord2f(0, 0);
  258.   glVertex3fv(p[4].pt);
  259.   if (flat) glTexCoord2fv(p[1].pt);
  260.   else glTexCoord2f(1, 0);
  261.   glVertex3fv(p[1].pt);
  262.   if (flat) glTexCoord2fv(p[10].pt);
  263.   else glTexCoord2f(1, 1);
  264.   glVertex3fv(p[10].pt);
  265.   if (flat) glTexCoord2fv(p[19].pt);
  266.   else glTexCoord2f(0, 1);
  267.   glVertex3fv(p[19].pt);
  268.   
  269.   glNormal3f(0, -1, 0);
  270.   if (flat) glTexCoord2fv(p[22].pt);
  271.   else glTexCoord2f(0, 0);
  272.   glVertex3fv(p[22].pt);
  273.   if (flat) glTexCoord2fv(p[16].pt);
  274.   else glTexCoord2f(1, 0);
  275.   glVertex3fv(p[16].pt);
  276.   if (flat) glTexCoord2fv(p[7].pt);
  277.   else glTexCoord2f(1, 1);
  278.   glVertex3fv(p[7].pt);
  279.   if (flat) glTexCoord2fv(p[13].pt);
  280.   else glTexCoord2f(0, 1);
  281.   glVertex3fv(p[13].pt);
  282.  
  283.   glNormal3f(0, 0, 1);
  284.   if (flat) glTexCoord2fv(p[14].pt);
  285.   else glTexCoord2f(0, 0);
  286.   glVertex3fv(p[14].pt);
  287.   if (flat) glTexCoord2fv(p[6].pt); 
  288.   else glTexCoord2f(1, 0);
  289.   glVertex3fv(p[6].pt);
  290.   if (flat) glTexCoord2fv(p[2].pt);
  291.   else glTexCoord2f(1, 1);
  292.   glVertex3fv(p[2].pt);
  293.   if (flat) glTexCoord2fv(p[3].pt);
  294.   else glTexCoord2f(0, 1);
  295.   glVertex3fv(p[3].pt);
  296.  
  297.   glNormal3f(0, 0, -1);
  298.   if (flat) glTexCoord2fv(p[20].pt);
  299.   else glTexCoord2f(0, 0);
  300.   glVertex3fv(p[20].pt);
  301.   if (flat) glTexCoord2fv(p[9].pt);
  302.   else glTexCoord2f(1, 0);
  303.   glVertex3fv(p[9].pt);
  304.   if (flat) glTexCoord2fv(p[17].pt);
  305.   else glTexCoord2f(1, 1);
  306.   glVertex3fv(p[17].pt);
  307.   if (flat) glTexCoord2fv(p[21].pt);
  308.   else glTexCoord2f(0, 1);
  309.   glVertex3fv(p[21].pt);
  310.  
  311.   glEnd();
  312. }
  313.  
  314. void Stone::draw_edges(int flat)
  315. {
  316.   draw_edges(points, flat);
  317. }
  318.  
  319. void Stone::draw_edges(Point *p, int flat)
  320. {
  321.   Point n1, n2;
  322.  
  323.   glBegin(GL_QUADS);
  324.  
  325.   n1.set(0, 1, 0);
  326.   n2.set(1, 0, 0);
  327.   draw_edge(n1, n2, p, 10, 1, 0, 11, flat);
  328.  
  329.   n1.set(1, 0, 0);
  330.   n2.set(0, -1, 0);
  331.   draw_edge(n1, n2, p, 15, 8, 7, 16, flat);
  332.  
  333.   n1.set(1, 0, 0);
  334.   n2.set(0, 0, 1);
  335.   draw_edge(n1, n2, p, 8, 0, 2, 6, flat);
  336.  
  337.   n1.set(1, 0, 0);
  338.   n2.set(0, 0, -1);
  339.   draw_edge(n1, n2, p, 11, 15, 17, 9, flat);
  340.  
  341.   n1.set(0, 1, 0);
  342.   n2.set(-1, 0, 0);
  343.   draw_edge(n1, n2, p, 4, 19, 18, 5, flat);
  344.  
  345.   n1.set(-1, 0, 0);
  346.   n2.set(0, -1, 0);
  347.   draw_edge(n1, n2, p, 12, 23, 22, 13, flat);
  348.   
  349.   n1.set(-1, 0, 0);
  350.   n2.set(0, 0, 1);
  351.   draw_edge(n1, n2, p, 5, 12, 14, 3, flat);
  352.  
  353.   n2.set(-1, 0, 0);
  354.   n1.set(0, 0, -1);
  355.   draw_edge(n1, n2, p, 20, 21, 23, 18, flat);
  356.     
  357.   n1.set(0, 1, 0);
  358.   n2.set(0, 0, 1);
  359.   draw_edge(n1, n2, p, 1, 4, 3, 2, flat);
  360.  
  361.   n1.set(0, 1, 0);
  362.   n2.set(0, 0, -1);
  363.   draw_edge(n1, n2, p, 19, 10, 9, 20, flat);
  364.  
  365.   n1.set(0, -1, 0);
  366.   n2.set(0, 0, 1);
  367.   draw_edge(n1, n2, p, 13, 7, 6, 14, flat);
  368.  
  369.   n1.set(0, -1, 0);
  370.   n2.set(0, 0, -1); 
  371.   draw_edge(n1, n2, p, 16, 22, 21, 17, flat);
  372.  
  373.   glEnd();
  374. }
  375.  
  376. void Stone::draw_edge(Point n1, Point n2, Point *p, 
  377.               int a, int b, int c, int d, int flat)
  378. {
  379.   glNormal3fv(n1.pt);
  380.   if (flat) glTexCoord2fv(p[a].pt);
  381.   else glTexCoord2f(0, 0);
  382.   glVertex3fv(p[a].pt);
  383.   if (flat) glTexCoord2fv(p[b].pt);
  384.   else glTexCoord2f(0, 1);
  385.   glVertex3fv(p[b].pt);
  386.   glNormal3fv(n2.pt);
  387.   if (flat) glTexCoord2fv(p[c].pt);
  388.   else glTexCoord2f(1, 1);
  389.   glVertex3fv(p[c].pt);
  390.   if (flat) glTexCoord2fv(p[d].pt);
  391.   else glTexCoord2f(1, 0);
  392.   glVertex3fv(p[d].pt);
  393. }
  394.  
  395. void Stone::draw_corners(Point *p, int flat)
  396. {
  397.   GLfloat e = 1.0 - erosion;
  398.  
  399.   glBegin(GL_TRIANGLES);
  400.  
  401.   if (flat) glTexCoord2fv(p[0].pt);
  402.   else glTexCoord2f(0, 0);
  403.   glNormal3f(1, 0, 0);
  404.   glVertex3fv(p[0].pt);
  405.   if (flat) glTexCoord2fv(p[1].pt);
  406.   else glTexCoord2f(1, 0);
  407.   glNormal3f(0, 1, 0);
  408.   glVertex3fv(p[1].pt);
  409.   if (flat) glTexCoord2fv(p[2].pt);
  410.   else glTexCoord2f(.5, 1);
  411.   glNormal3f(0, 0, 1);
  412.   glVertex3fv(p[2].pt);
  413.  
  414.   if (flat) glTexCoord2fv(p[3].pt); 
  415.   else glTexCoord2f(0, 0);
  416.   glNormal3f(0, 0, 1);
  417.   glVertex3fv(p[3].pt);
  418.   if (flat) glTexCoord2fv(p[4].pt); 
  419.   else glTexCoord2f(1, 0);
  420.   glNormal3f(0, 1, 0);
  421.   glVertex3fv(p[4].pt);
  422.   if (flat) glTexCoord2fv(p[5].pt); 
  423.   else glTexCoord2f(.5, 1);
  424.   glNormal3f(-1, 0, 0);
  425.   glVertex3fv(p[5].pt);
  426.  
  427.   if (flat) glTexCoord2fv(p[6].pt); 
  428.   else glTexCoord2f(0, 0);
  429.   glNormal3f(0, 0, 1);
  430.   glVertex3fv(p[6].pt);
  431.   if (flat) glTexCoord2fv(p[7].pt); 
  432.   else glTexCoord2f(1, 0);
  433.   glNormal3f(0, -1, 0);
  434.   glVertex3fv(p[7].pt);
  435.   if (flat) glTexCoord2fv(p[8].pt); 
  436.   else glTexCoord2f(.5, 1);
  437.   glNormal3f(1, 0, 0);
  438.   glVertex3fv(p[8].pt);
  439.  
  440.   if (flat) glTexCoord2fv(p[9].pt); 
  441.   else glTexCoord2f(0, 0);
  442.   glNormal3f(0, 0, -1);
  443.   glVertex3fv(p[9].pt);
  444.   if (flat) glTexCoord2fv(p[10].pt); 
  445.   else glTexCoord2f(1, 0);
  446.   glNormal3f(0, 1, 0);
  447.   glVertex3fv(p[10].pt);
  448.   if (flat) glTexCoord2fv(p[11].pt); 
  449.   else glTexCoord2f(.5, 1);
  450.   glNormal3f(1, 0, 0);
  451.   glVertex3fv(p[11].pt);
  452.  
  453.   if (flat) glTexCoord2fv(p[12].pt); 
  454.   else glTexCoord2f(0, 0);
  455.   glNormal3f(-1, 0, 0);
  456.   glVertex3fv(p[12].pt);
  457.   if (flat) glTexCoord2fv(p[13].pt); 
  458.   else glTexCoord2f(1, 0);
  459.   glNormal3f(0, -1, 0);
  460.   glVertex3fv(p[13].pt);
  461.   if (flat) glTexCoord2fv(p[14].pt); 
  462.   else glTexCoord2f(.5, 1);
  463.   glNormal3f(0, 0, 1);
  464.   glVertex3fv(p[14].pt);
  465.  
  466.   if (flat) glTexCoord2fv(p[15].pt); 
  467.   else glTexCoord2f(0, 0);
  468.   glNormal3f(1, 0, 0);
  469.   glVertex3fv(p[15].pt);
  470.   if (flat) glTexCoord2fv(p[16].pt); 
  471.   else glTexCoord2f(1, 0);
  472.   glNormal3f(0, -1, 0);
  473.   glVertex3fv(p[16].pt);
  474.   if (flat) glTexCoord2fv(p[17].pt); 
  475.   else glTexCoord2f(.5, 1);
  476.   glNormal3f(0, 0, -1);
  477.   glVertex3fv(p[17].pt);
  478.  
  479.   if (flat) glTexCoord2fv(p[18].pt); 
  480.   else glTexCoord2f(0, 0);
  481.   glNormal3f(-1, 0, 0);
  482.   glVertex3fv(p[18].pt);
  483.   if (flat) glTexCoord2fv(p[19].pt); 
  484.   else glTexCoord2f(1, 0);
  485.   glNormal3f(0, 1, 0);
  486.   glVertex3fv(p[19].pt);
  487.   if (flat) glTexCoord2fv(p[20].pt); 
  488.   else glTexCoord2f(.5, 1);
  489.   glNormal3f(0, 0, -1);
  490.   glVertex3fv(p[20].pt);
  491.  
  492.   if (flat) glTexCoord2fv(p[21].pt); 
  493.   else glTexCoord2f(0, 0);
  494.   glNormal3f(0, 0, -1);
  495.   glVertex3fv(p[21].pt);
  496.   if (flat) glTexCoord2fv(p[22].pt); 
  497.   else glTexCoord2f(1, 0);
  498.   glNormal3f(0, -1, 0);
  499.   glVertex3fv(p[22].pt);
  500.   if (flat) glTexCoord2fv(p[23].pt); 
  501.   else glTexCoord2f(.5, 1);
  502.   glNormal3f(-1, 0, 0);
  503.   glVertex3fv(p[23].pt);
  504.  
  505.   glEnd();
  506. }
  507.  
  508. void Stone::draw_shadow(Point dlight) 
  509. {
  510.   Point p[24];
  511.   int i;
  512.  
  513.   transform_points();
  514.   for (i = 0; i < 24; i++) {
  515.     p[i] = points[i];
  516.     if (p[i].pt[2] < 0.0) p[i].pt[2] = 0.0;
  517.     p[i] = p[i].project_direction(dlight);
  518.   }
  519.   draw_faces(p, 1);
  520.   draw_edges(p, 1);
  521.   draw_corners(p, 1);
  522. }
  523.  
  524. void Stone::draw_shadow(Point dlight, GLfloat blur, 
  525.             Color color, Color diffuse)
  526. {
  527.   float b = 1.0 + blur;
  528.   float c, s;
  529.   Point p[8], pp[8];
  530.   Point d, n;
  531.   Color colorp, diffusep;
  532.   int draw[6];
  533.   int i;
  534.  
  535.   if (blur == 0.0) {
  536.     draw_shadow(dlight);
  537.     return;
  538.   }
  539.  
  540.   colorp = color;
  541.   color.c[3] = 1;
  542.   colorp.c[3] = 0;
  543.   diffusep = diffuse;
  544.   diffuse.c[3] = 1;
  545.   diffusep.c[3] = 0;
  546.  
  547.   /* We're being slightly cowardly here and ignoring the erosion - it
  548.    * shouldn't make a big difference */
  549.   p[0].set(-1, -1, -1);
  550.   pp[0] = p[0];
  551.   p[1].set(1, -1, -1);
  552.   pp[1] = p[1];
  553.   p[2].set(1, 1, -1);
  554.   pp[2] = p[2];
  555.   p[3].set(-1, 1, -1);
  556.   pp[3] = p[3];
  557.   p[4].set(-1, -1, 1);
  558.   pp[4] = p[4];
  559.   p[5].set(1, -1, 1);
  560.   pp[5] = p[5];
  561.   p[6].set(1, 1, 1);
  562.   pp[6] = p[6];
  563.   p[7].set(-1, 1, 1);
  564.   pp[7] = p[7];
  565.  
  566.   c = cos(radians(rotation));
  567.   s = sin(radians(rotation));
  568.   for (i = 0; i < 8; i++) {
  569.     p[i] = transform_point(p[i], c, s);
  570.  
  571.     /* This is a complete and utter hack - the net effect is that
  572.      * points which are higher are displaced further when the penumbra 
  573.      * is drawn */
  574.     d = dimensions;
  575.     d.pt[0] += blur * (pp[i].pt[2] + translation.pt[2]);
  576.     d.pt[1] += blur * (pp[i].pt[2] + translation.pt[2]);
  577.     d.pt[2] += blur * (pp[i].pt[2] + translation.pt[2]);
  578.     pp[i] = pp[i].scale(d);
  579.     pp[i] = trans_rot_point(pp[i], c, s);
  580.     if (p[i].pt[2] < 0.0) p[i].pt[2] = 0.0;
  581.  
  582.     p[i] = p[i].project_direction(dlight);
  583.     if (pp[i].pt[2] < 0.0) pp[i].pt[2] = 0.0;
  584.     pp[i] = pp[i].project_direction(dlight);
  585.   }
  586.  
  587.   /* Compute whether or not we should draw various parts of the shadow
  588.    * based upon the normal direction */
  589.   if (dlight.pt[2] > 0.0) dlight *= -1.0;
  590.   n.set(0, 0, -1);
  591.   n = n.rotate_aboutz(c, s);
  592.   draw[0] = (dlight.dot(n) < 0.0);
  593.   n.set(0, -1, 0);
  594.   n = n.rotate_aboutz(c, s);
  595.   draw[1] = (dlight.dot(n) < 0.0);
  596.   n.set(1, 0, 0);
  597.   n = n.rotate_aboutz(c, s);
  598.   draw[2] = (dlight.dot(n) < 0.0);
  599.   n.set(0, 1, 0);
  600.   n = n.rotate_aboutz(c, s);
  601.   draw[3] = (dlight.dot(n) < 0.0);
  602.   n.set(-1, 0, 0);
  603.   n = n.rotate_aboutz(c, s);
  604.   draw[4] = (dlight.dot(n) < 0.0);
  605.   n.set(0, 0, 1);
  606.   n = n.rotate_aboutz(c, s);
  607.   draw[5] = (dlight.dot(n) < 0.0);
  608.  
  609.   /* This part draws the "real" shadow */
  610.   glColor4fv(color.c);
  611.   glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  612.  
  613.   glBegin(GL_QUADS);
  614.  
  615.   if (draw[0]) {
  616.     glVertex2fv(p[0].pt);
  617.     glVertex2fv(p[1].pt);
  618.     glVertex2fv(p[2].pt);
  619.     glVertex2fv(p[3].pt);
  620.   }
  621.  
  622.   if (draw[1]) {
  623.     glVertex2fv(p[0].pt);
  624.     glVertex2fv(p[1].pt);
  625.     glVertex2fv(p[5].pt);
  626.     glVertex2fv(p[4].pt);
  627.   }
  628.  
  629.   if (draw[2]) {
  630.     glVertex2fv(p[1].pt);
  631.     glVertex2fv(p[2].pt);
  632.     glVertex2fv(p[6].pt);
  633.     glVertex2fv(p[5].pt);
  634.   }
  635.  
  636.   if (draw[3]) {
  637.     glVertex2fv(p[2].pt);
  638.     glVertex2fv(p[3].pt);
  639.     glVertex2fv(p[7].pt);
  640.     glVertex2fv(p[6].pt);
  641.   }
  642.  
  643.   if (draw[4]) {
  644.     glVertex2fv(p[3].pt);
  645.     glVertex2fv(p[0].pt);
  646.     glVertex2fv(p[4].pt);
  647.     glVertex2fv(p[7].pt);
  648.   }
  649.  
  650.   if (draw[5]) {
  651.     glVertex2fv(p[4].pt);
  652.     glVertex2fv(p[5].pt);
  653.     glVertex2fv(p[6].pt);
  654.     glVertex2fv(p[7].pt);
  655.   }
  656.  
  657.   glEnd();
  658.  
  659.   /* This part draws the penumbra */
  660.  
  661.   glEnable(GL_BLEND);
  662.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  663.  
  664.   glBegin(GL_QUADS);
  665.  
  666.   /* Top */
  667.   if (draw[5]) {
  668.     if (!draw[4]) {
  669.       glColor4fv(color.c);
  670.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  671.       glVertex2fv(p[4].pt);
  672.       glVertex2fv(p[5].pt);
  673.       glColor4fv(colorp.c);
  674.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  675.       glVertex2fv(pp[5].pt);
  676.       glVertex2fv(pp[4].pt);
  677.     }
  678.  
  679.     if (!draw[2]) {
  680.       glColor4fv(color.c);
  681.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  682.       glVertex2fv(p[5].pt);
  683.       glVertex2fv(p[6].pt);
  684.       glColor4fv(colorp.c);
  685.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  686.       glVertex2fv(pp[6].pt);
  687.       glVertex2fv(pp[5].pt);
  688.     }
  689.  
  690.     if (!draw[3]) {
  691.       glColor4fv(color.c);
  692.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  693.       glVertex2fv(p[6].pt);
  694.       glVertex2fv(p[7].pt);
  695.       glColor4fv(colorp.c);
  696.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  697.       glVertex2fv(pp[7].pt);
  698.       glVertex2fv(pp[6].pt);
  699.     }
  700.  
  701.     if (!draw[4]) {
  702.       glColor4fv(color.c);
  703.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  704.       glVertex2fv(p[7].pt);
  705.       glVertex2fv(p[4].pt);
  706.       glColor4fv(colorp.c);
  707.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  708.       glVertex2fv(pp[4].pt);
  709.       glVertex2fv(pp[7].pt);
  710.     }
  711.   }
  712.   /* End of Top */
  713.  
  714.   /* Sides */
  715.   if ((draw[1] || draw[4]) && !(draw[1] && draw[4])) {
  716.     glColor4fv(color.c);
  717.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  718.     glVertex2fv(p[0].pt);
  719.     glVertex2fv(p[4].pt);
  720.     glColor4fv(colorp.c);
  721.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  722.     glVertex2fv(pp[4].pt);
  723.     glVertex2fv(pp[0].pt);
  724.   }
  725.  
  726.   if ((draw[1] || draw[2]) && !(draw[1] && draw[2])) {
  727.     glColor4fv(color.c);
  728.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  729.     glVertex2fv(p[1].pt);
  730.     glVertex2fv(p[5].pt);
  731.     glColor4fv(colorp.c);
  732.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  733.     glVertex2fv(pp[5].pt);
  734.     glVertex2fv(pp[1].pt);
  735.   }
  736.  
  737.   if ((draw[3] || draw[2]) && !(draw[3] && draw[2])) {
  738.     glColor4fv(color.c);
  739.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  740.     glVertex2fv(p[2].pt);
  741.     glVertex2fv(p[6].pt);
  742.     glColor4fv(colorp.c);
  743.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  744.     glVertex2fv(pp[6].pt);
  745.     glVertex2fv(pp[2].pt);
  746.   }
  747.  
  748.   if ((draw[3] || draw[4]) && !(draw[3] && draw[4])) {
  749.     glColor4fv(color.c);
  750.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  751.     glVertex2fv(p[3].pt);
  752.     glVertex2fv(p[7].pt);
  753.     glColor4fv(colorp.c);
  754.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  755.     glVertex2fv(pp[7].pt);
  756.     glVertex2fv(pp[3].pt);
  757.   }
  758.   /* End of Sides */
  759.  
  760.   /* Bottom */
  761.   if (draw[0]) {
  762.     if (!draw[1]) {
  763.       glColor4fv(color.c);
  764.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  765.       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, diffuse.c);
  766.       glVertex2fv(p[0].pt);
  767.       glVertex2fv(p[1].pt);
  768.       glColor4fv(colorp.c);
  769.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  770.       glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, diffusep.c);
  771.       glVertex2fv(pp[1].pt);
  772.       glVertex2fv(pp[0].pt);
  773.     }
  774.     
  775.     if (!draw[2]) {
  776.       glColor4fv(color.c);
  777.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  778.       glVertex2fv(p[1].pt);
  779.       glVertex2fv(p[2].pt);
  780.       glColor4fv(colorp.c);
  781.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  782.       glVertex2fv(pp[2].pt);
  783.       glVertex2fv(pp[1].pt);
  784.     }
  785.  
  786.     if (!draw[3]) {
  787.       glColor4fv(color.c);
  788.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  789.       glVertex2fv(p[2].pt);
  790.       glVertex2fv(p[3].pt);
  791.       glColor4fv(colorp.c);
  792.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  793.       glVertex2fv(pp[3].pt);
  794.       glVertex2fv(pp[2].pt);
  795.     }
  796.     
  797.     if (!draw[4]) {
  798.       glColor4fv(color.c);
  799.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse.c);
  800.       glVertex2fv(p[3].pt);
  801.       glVertex2fv(p[0].pt);
  802.       glColor4fv(colorp.c);
  803.       glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffusep.c);
  804.       glVertex2fv(pp[0].pt);
  805.       glVertex2fv(pp[3].pt);
  806.     }
  807.   }
  808.   /* End of Bottom */
  809.  
  810.   glEnd();
  811.  
  812.   glDisable(GL_BLEND);
  813.  
  814. }
  815.  
  816.